package com.scpii.universal.concurrent.executor;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

@SuppressWarnings("deprecation")
public class HttpClientExecutor {
	private static final int DEFAULT_MAX_CONNECTIONS = 5;
	private static final int TIMEOUT = 10000;
	private static final int TIMEOUT_SOCKET = 15000;

	private ClientConnectionManager connectionManager;
	private HttpClient httpClient;

	/************ Singleton ***********/
	private static HttpClientExecutor instance = new HttpClientExecutor();

	private HttpClientExecutor() {
		HttpParams params = new BasicHttpParams();
		HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
		HttpProtocolParams.setContentCharset(params,
				HTTP.DEFAULT_CONTENT_CHARSET);
		HttpProtocolParams.setUseExpectContinue(params, true);

		// 自定义三个timeout参数
		ConnManagerParams.setTimeout(params, 5000);
		ConnManagerParams.setMaxTotalConnections(params,
				DEFAULT_MAX_CONNECTIONS);
		HttpConnectionParams.setConnectionTimeout(params, TIMEOUT);
		HttpConnectionParams.setSoTimeout(params, TIMEOUT_SOCKET);

		SchemeRegistry schReg = new SchemeRegistry();
		schReg.register(new Scheme("http", PlainSocketFactory
				.getSocketFactory(), 80));
		schReg.register(new Scheme("https",
				SSLSocketFactory.getSocketFactory(), 443));

		ClientConnectionManager conMgr = new ThreadSafeClientConnManager(
				params, schReg);

		httpClient = new DefaultHttpClient(conMgr, params);

	}

	public static HttpClientExecutor getInstance() {
		return instance;
	}

	/************ Singleton ***********/

	public void shutdown() {
		connectionManager.shutdown();
	}

	/**
	 * 创建自适应网络的 HttpPost
	 */
	private HttpPost newHttpPost(String destUrl) throws Exception {
		HttpPost httpPost = new HttpPost(destUrl);
		httpPost.setHeader("accept", "*/*");

		return httpPost;
	}

	/**
	 * 创建自适应网络的 HttpGet
	 */
	private HttpGet newHttpGet(String destUrl) throws Exception {
		HttpGet httpGet = new HttpGet(destUrl);
		httpGet.setHeader("accept", "*/*");

		return httpGet;
	}

	/**
	 * 执行 POST 请求，POST 请求的服务器响应
	 */
	public byte[] executePost(String url, byte[] entity) {
		byte[] resData = null;
		HttpPost httpPost = null;
		try {

			httpPost = this.newHttpPost(url);

			// 设置 post 参数
			if (entity != null && entity.length > 0) {
				httpPost.setEntity(new ByteArrayEntity(entity));
			}

			// 发送请求
			HttpResponse httpResponse = httpClient.execute(httpPost);
			// 处理返回消息
			StatusLine statusLine = null;
			if (httpResponse == null
					|| (statusLine = httpResponse.getStatusLine()) == null)
				return null;

			int responseCode = statusLine.getStatusCode();

			if (responseCode == HttpStatus.SC_OK) {
				resData = EntityUtils.toByteArray(httpResponse.getEntity());
			}
		} catch (Exception e) {
			e.printStackTrace();
			if (httpPost != null) {
				httpPost.abort();
			}
		} finally {
			if (httpPost != null) {
				httpPost.releaseConnection();
			}
		}
		return resData;
	}

	/**
	 * 执行 GET 请求，GET 请求的服务器响应为指定资源类型
	 */
	public byte[] executeGet(String url) {
		byte[] resData = null;
		HttpGet httpGet = null;
		try {

			httpGet = this.newHttpGet(url);
			// 发送请求
			HttpResponse httpResponse = httpClient.execute(httpGet);

			// 处理返回消息
			StatusLine statusLine = null;
			if (httpResponse == null
					|| (statusLine = httpResponse.getStatusLine()) == null)
				return null;

			int responseCode = statusLine.getStatusCode();

			if (responseCode == HttpStatus.SC_OK) {
				resData = EntityUtils.toByteArray(httpResponse.getEntity());
			}

		} catch (Exception e) {
			e.printStackTrace();
			if (httpGet != null) {
				httpGet.abort();
			}

		} finally {
			if (httpGet != null) {
				httpGet.releaseConnection();
			}
		}
		return resData;
	}

}
